package controller

import (
	"backend/dao/mysql"
	"backend/models"
	"backend/utils/api"
	"backend/utils/jwt"
	"backend/validators"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"net/http"
	"strings"
)

// SignUpHandler 用户注册视图
func SignUpHandler(c *gin.Context) {
	// 获取请求体参数 校验数据有效性
	var rf validators.RegisterForm
	if err := c.ShouldBind(&rf); err != nil {
		zap.L().Error("请求参数错误", zap.Error(err))
		api.ResponseError(c, api.CodeInvalidParams)
		return
	}

	// 注册用户
	err := mysql.Register(&models.User{
		Username: rf.Username,
		Password: rf.Password,
	})
	if errors.Is(err, api.ErrorUserExit) {
		api.ResponseError(c, api.CodeUserExist)
		return
	}
	if err != nil {
		zap.L().Error("注册用户失败", zap.Error(err))
		api.ResponseError(c, api.CodeServerBusy)
		return
	}
	api.ResponseSuccess(c, nil)
}

// LoginHandler 用户登录视图
func LoginHandler(c *gin.Context) {
	// 获取请求体参数 校验数据有效性
	var lf validators.LoginForm
	if err := c.ShouldBind(&lf); err != nil {
		zap.L().Error("请求参数错误", zap.Error(err))
		api.ResponseError(c, api.CodeInvalidParams)
		return
	}
	// 检验用户名和密码是否正确
	if err := mysql.Login(lf.Username, lf.Password); err != nil {
		zap.L().Error("登录失败", zap.Error(err))
		api.ResponseError(c, api.CodeInvalidParams)
		return
	}

	// 生成token
	accessToken, refreshToken, _ := jwt.GenToken(lf.UserId)
	api.ResponseSuccess(c, gin.H{
		"access_token":  accessToken,
		"refresh_token": refreshToken,
		"user_id":       lf.UserId,
		"user_name":     lf.Username,
	})
}

// RefreshTokenHandler 刷新token视图
func RefreshTokenHandler(c *gin.Context) {
	rt := c.Query("refresh_token")
	// 客户端携带Token有三种方式 1.放在请求头 2.放在请求体 3.放在URI
	// 这里假设Token放在Header的Authorization中，并使用Bearer开头
	// 这里的具体实现方式要依据你的实际业务情况决定
	authHeader := c.Request.Header.Get("Authorization")
	if authHeader == "" {
		api.ResponseErrorWithMsg(c, api.CodeInvalidToken, "请求头缺少Auth Token")
		c.Abort()
		return
	}
	// 按空格分割
	parts := strings.SplitN(authHeader, " ", 2)
	if !(len(parts) == 2 && parts[0] == "Bearer") {
		api.ResponseErrorWithMsg(c, api.CodeInvalidToken, "Token格式不对")
		c.Abort()
		return
	}
	aToken, rToken, err := jwt.RefreshToken(parts[1], rt)
	fmt.Println(err)
	c.JSON(http.StatusOK, gin.H{
		"access_token":  aToken,
		"refresh_token": rToken,
	})
}
